<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="./js/ctx.js"></script>
</head>
<style>
    .demo-container {
        background-color: #303336;
        border-radius: 5px;
        padding: 5px;
        margin: 5px 3px;
    }
    .demo-container input {
        vertical-align: middle;
        margin-top: 0;
    }
</style>
<body>
<div id="cesiumContainer"></div>
<div id="toolbar">
    <div id="zoomButtons"></div>
    <div class="demo-container">
        <label><input type="radio" name="shadingMaterials" value="none" data-bind="checked: selectedShading"> No shading</label>
        <label><input type="radio" name="shadingMaterials" value="elevation" data-bind="checked: selectedShading"> Elevation</label>
        <label><input type="radio" name="shadingMaterials" value="slope" data-bind="checked: selectedShading"> Slope</label>
    </div>
    <div class="demo-container">
        <div>
            <label><input type="checkbox" data-bind="checked: enableContour">Enable Contour Lines</label>
        </div>
        <div>
            Spacing <input style="width: 136px" type="range" min="1.0" max="500.0" step="1.0" data-bind="value: contourSpacing, valueUpdate: 'input', enable: enableContour"> <span data-bind="text: contourSpacing"></span>m
        </div>
        <div>
            Line Width <input style="width: 125px" type="range" min="1.0" max="10.0" step="1.0" data-bind="value: contourWidth, valueUpdate: 'input', enable: enableContour"> <span data-bind="text: contourWidth"></span>px
        </div>
        <div>
            <button type="button" data-bind="click: changeColor, enable: enableContour">Change contour color</button>
        </div>
    </div>
</div>
<script>
    var initCesium = new InitCesium();
    var viewer = initCesium.initViewer('cesiumContainer', {
        terrainExaggeration : 2.0,
        terrainProvider: Cesium.createWorldTerrain()
    });
    viewer.scene.globe.enableLighting = false;

    function getElevationContourMaterial() {
        // Creates a composite material with both elevation shading and contour lines
        return new Cesium.Material({
            fabric: {
                type: 'ElevationColorContour',
                materials: {
                    contourMaterial: {
                        type: 'ElevationContour'
                    },
                    elevationRampMaterial: {
                        type: 'ElevationRamp'
                    }
                },
                components: {
                    diffuse: 'contourMaterial.alpha == 0.0 ? elevationRampMaterial.diffuse : contourMaterial.diffuse',
                    alpha: 'max(contourMaterial.alpha, elevationRampMaterial.alpha)'
                }
            },
            translucent: false
        });
    }

    function getSlopeContourMaterial() {
        // Creates a composite material with both slope shading and contour lines
        return new Cesium.Material({
            fabric: {
                type: 'SlopeColorContour',
                materials: {
                    contourMaterial: {
                        type: 'ElevationContour'
                    },
                    slopeRampMaterial: {
                        type: 'SlopeRamp'
                    }
                },
                components: {
                    diffuse: 'contourMaterial.alpha == 0.0 ? slopeRampMaterial.diffuse : contourMaterial.diffuse',
                    alpha: 'max(contourMaterial.alpha, slopeRampMaterial.alpha)'
                }
            },
            translucent: false
        });
    }

    var elevationRamp = [0.0, 0.045, 0.1, 0.15, 0.37, 0.54, 1.0];
    var slopeRamp = [0.0, 0.29, 0.5, Math.sqrt(2)/2, 0.87, 0.91, 1.0];
    function getColorRamp(selectedShading) {
        var ramp = document.createElement('canvas');
        ramp.width = 100;
        ramp.height = 1;
        var ctx = ramp.getContext('2d');

        var values = selectedShading === 'elevation' ? elevationRamp : slopeRamp;

        var grd = ctx.createLinearGradient(0, 0, 100, 0);
        grd.addColorStop(values[0], '#000000'); //black
        grd.addColorStop(values[1], '#2747E0'); //blue
        grd.addColorStop(values[2], '#D33B7D'); //pink
        grd.addColorStop(values[3], '#D33038'); //red
        grd.addColorStop(values[4], '#FF9742'); //orange
        grd.addColorStop(values[5], '#ffd700'); //yellow
        grd.addColorStop(values[6], '#ffffff'); //white

        ctx.fillStyle = grd;
        ctx.fillRect(0, 0, 100, 1);

        return ramp;
    }

    var minHeight = -414.0; // approximate dead sea elevation
    var maxHeight = 8777.0; // approximate everest elevation
    var contourColor = Cesium.Color.RED.clone();
    var contourUniforms = {};
    var shadingUniforms = {};

    // The viewModel tracks the state of our mini application.
    var viewModel = {
        enableContour: false,
        contourSpacing: 150.0,
        contourWidth: 2.0,
        selectedShading: 'elevation',
        changeColor: function() {
            contourUniforms.color = Cesium.Color.fromRandom({alpha: 1.0}, contourColor);
        }
    };

    // Convert the viewModel members into knockout observables.
    Cesium.knockout.track(viewModel);

    // Bind the viewModel to the DOM elements of the UI that call for it.
    var toolbar = document.getElementById('toolbar');
    Cesium.knockout.applyBindings(viewModel, toolbar);

    function updateMaterial() {
        var hasContour = viewModel.enableContour;
        var selectedShading = viewModel.selectedShading;
        var globe = viewer.scene.globe;
        var material;
        if (hasContour) {
            if (selectedShading === 'elevation') {
                material = getElevationContourMaterial();
                shadingUniforms = material.materials.elevationRampMaterial.uniforms;
                shadingUniforms.minHeight = minHeight;
                shadingUniforms.maxHeight = maxHeight;
                contourUniforms = material.materials.contourMaterial.uniforms;
            } else if (selectedShading === 'slope') {
                material = getSlopeContourMaterial();
                shadingUniforms = material.materials.slopeRampMaterial.uniforms;
                contourUniforms = material.materials.contourMaterial.uniforms;
            } else {
                material = Cesium.Material.fromType('ElevationContour');
                contourUniforms = material.uniforms;
            }
            contourUniforms.width = viewModel.contourWidth;
            contourUniforms.spacing = viewModel.contourSpacing;
            contourUniforms.color = contourColor;
        } else if (selectedShading === 'elevation') {
            material = Cesium.Material.fromType('ElevationRamp');
            shadingUniforms = material.uniforms;
            shadingUniforms.minHeight = minHeight;
            shadingUniforms.maxHeight = maxHeight;
        } else if (selectedShading === 'slope') {
            material = Cesium.Material.fromType('SlopeRamp');
            shadingUniforms = material.uniforms;
        }
        if (selectedShading !== 'none') {
            shadingUniforms.image = getColorRamp(selectedShading);
        }

        globe.material = material;
    }

    updateMaterial();

    Cesium.knockout.getObservable(viewModel, 'enableContour').subscribe(function(newValue) {
        updateMaterial();
    });

    Cesium.knockout.getObservable(viewModel, 'contourWidth').subscribe(function(newValue) {
        contourUniforms.width = parseFloat(newValue);
    });

    Cesium.knockout.getObservable(viewModel, 'contourSpacing').subscribe(function(newValue) {
        contourUniforms.spacing = parseFloat(newValue);
    });

    Cesium.knockout.getObservable(viewModel, 'selectedShading').subscribe(function(value) {
        updateMaterial();
    });

    Sandcastle.addToolbarMenu([{
        text : 'Himalayas',
        onselect : function() {
            viewer.camera.setView({
                destination: new Cesium.Cartesian3(322100.7492728492, 5917960.047024654, 3077602.646977297),
                orientation: {
                    heading: 5.988151498702285,
                    pitch: -1.5614542839414822,
                    roll: 0
                }
            });
            viewer.clockViewModel.currentTime = Cesium.JulianDate.fromIso8601('2017-09-22T04:00:00Z');
        }
    }, {
        text : 'Half Dome',
        onselect : function() {
            viewer.camera.setView({
                destination: new Cesium.Cartesian3(-2495709.521843174, -4391600.804712465, 3884463.7192916023),
                orientation: {
                    heading: 1.7183056487769202,
                    pitch: -0.06460370548034144,
                    roll: 0.0079181631783527
                }
            });
            viewer.clockViewModel.currentTime = Cesium.JulianDate.fromIso8601('2017-09-22T18:00:00Z');
        }
    }, {
        text : 'Vancouver',
        onselect : function() {
            viewer.camera.setView({
                destination: new Cesium.Cartesian3(-2301222.367751603, -3485269.915771613, 4812080.961755785),
                orientation: {
                    heading: 0.11355958593902571,
                    pitch: -0.260011078090858,
                    roll: 0.00039019018274721873
                }
            });
            viewer.clockViewModel.currentTime = Cesium.JulianDate.fromIso8601('2017-09-22T18:00:00Z');
        }
    }, {
        text : 'Mount Everest',
        onselect : function() {
            viewer.camera.setView({
                destination: new Cesium.Cartesian3(282157.6960889096, 5638892.465594703, 2978736.186473513),
                orientation: {
                    heading: 4.747266966349747,
                    pitch: -0.2206998858596192,
                    roll: 6.280340554587955
                }
            });
            viewer.clockViewModel.currentTime = Cesium.JulianDate.fromIso8601('2017-09-22T04:00:00Z');
        }
    }], 'zoomButtons');



</script>
</body>
</html>